#include <stdio.h>
#include <error.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>

#define MAXLINE 1024
#define MAXARGS 128

void parse_massage(char* cmd, char* massage[]);
void printf_childstatus(int status);

int main(int argc, char* argv[])
{
    char cmd[MAXLINE];
    char* massage[MAXARGS];

    while(1)
    {
        printf("%s","simple_shell>");
        //用户输入命令读取命令字符串
        fgets(cmd, MAXLINE, stdin);
        //fgets函数 会读取\n
        //如果cmd为exit 则终止进程
        if(strcmp(cmd, "exit\n") == 0)
        {
            exit(1);
        }
        //创建子进程来执行程序
        pid_t childpid = fork();
        int status;
        switch(childpid)
        {
            case -1:
                return -1;
            case 0: //子进程
                //解析命令行参数
                parse_massage(cmd, massage);
                //这里要设置函数簇中的p,因为执行不同的命令会有不同的路径，这里设置p在环境变量中进行查找
                // 可以设置v就是命令行参数以数组的形式指定 
                if(execvp(massage[0], massage) == -1)
                    error(1, errno, "execvp");

            default:    //父进程
                //等待子进程执行完成
                if(waitpid(childpid, &status, 0) == -1)
                {
                    error(1, errno, "waitpid");
                }
                //打印子进程的终止状态信息
                printf_childstatus(status);
        }
    }
    return 0;
}

void printf_childstatus(int status)
{
    //是否正常退出
    if(WIFEXITED(status))
    {
        //是打印
        printf("Exit code:%d\n", WEXITSTATUS(status));
    }
    else if(WIFSIGNALED(status))//是否异常退出
    {
        //是打印出现异常终止的信号
        printf("Terminate signal:%d\n", WTERMSIG(status));
    }
#ifdef WCOREDUMP
    if(WCOREDUMP(status))
    {
        printf("Core Dump\n");
    }
#endif
}

//cmd 为接收到的用户字符串   massage为要存放解析后的命令行参数
void parse_massage(char* cmd, char* massage[])
{
    int i = 0;
    massage[i] = strtok(cmd, " \t\n");
    while(massage[i] != NULL)
    {
        i++;
        massage[i] = strtok(NULL, " \t\n");
    }
}